package LeetDev.a3d;

import javax.microedition.khronos.opengles.GL10;

public class Camera extends Node {
	private Vect m_lookAt;
	private Vect m_up;
	private float m_fov;
	private float m_near;
	private float m_far;
	private static Camera s_currentCamera; /*! The current camera in use. Might be null. */

	private static Vect view=new Vect();
	private static Vect up=new Vect();
	private static Vect right=new Vect();
	private static float m[]=new float[16];

	public Camera(Vect pos, final Vect lookat, final Vect up, float fov, float pnear, float pfar)
	{
		super();
		setPosition(pos);
		setLookAt(lookat);
		setUp(up);
		setFov(fov);
		setNear(pnear);
		setFar(pfar);
	}
	
	public void setLookAt(final Vect lookat)
	{
		m_lookAt=lookat;
	}
	public void setLookAt(final float x, final float y, final float z)
	{
		m_lookAt.x=x;
		m_lookAt.y=y;
		m_lookAt.z=z;
	}
	public Vect getLookAt()
	{
		return(m_lookAt);
	}

	public void setUp(final Vect up)
	{
		m_up=up;
	}
	public void setUp(final float x, final float y, final float z)
	{
		m_up.x=x;
		m_up.y=y;
		m_up.z=z;
	}
	public Vect getUp()
	{
		return(m_up);
	}

	public void setFov(final float fov)
	{
		m_fov=fov;
	}
	public float getFov()
	{
		return(m_fov);
	}

	public void setNear(final float pnear)
	{
		m_near=pnear;
	}
	public float getNear()
	{
		return(m_near);
	}

	public void setFar(final float pfar)
	{
		m_far=pfar;
	}
	public float getFar()
	{
		return(m_far);
	}

	public void gluPerspective(GL10 gl, final float fovy, final float aspect, final float zNear, final float zFar)
	{
		float f = (float) (1.0/Math.tan((fovy * 3.1415926) / 360.0));
		
		for(int i=16;--i>=0;)
		{
			m[i]=0;
		}
		m[0]=f/aspect;
		m[5]=f;
		m[10]=(zFar+zNear)/(zNear-zFar);
		m[11]=-1;
		m[14]=(2*zFar*zNear)/(zNear-zFar);
		gl.glMultMatrixf(m,0);
	}

	public void draw(GL10 gl)
	{
		s_currentCamera=this;
		gl.glMatrixMode(GL10.GL_PROJECTION);
		gl.glLoadIdentity();
		if(m_fov<=0)
		{
			// ortho camera
			float w=(float)(Engine.instance().getWidth()>>1);
			float h=(float)(Engine.instance().getHeight()>>1);
			gl.glOrthof(-w,w,-h,h,m_near,m_far);
		}
		else
		{
			gluPerspective(gl,m_fov,Engine.instance().getAspect(),m_near,m_far);
		}
		// gluLookAt replacement
		m_position.sub(m_lookAt,view);
		view.normalize();
		m_up.cross(view,right);
		right.normalize();
		view.cross(right,up);
		up.normalize();
		m[0]=right.x;m[4]=right.y;m[8]=right.z;m[12]=0;
		m[1]=up.x;m[5]=up.y;m[9]=up.z;m[13]=0;
		m[2]=view.x;m[6]=view.y;m[10]=view.z;m[14]=0;
		m[3]=0;m[7]=0;m[11]=0;m[15]=1;
		gl.glMultMatrixf(m,0);
		gl.glTranslatef(-m_position.x,-m_position.y,-m_position.z);
	// The use of a camera is considered to be a new scene, so we clear all used lights when a new camera is used.
		Light.resetLights(gl);
	}
	
	public void animate(GL10 gl, double ticks, double delta)
	{
		s_currentCamera=this;
	}

	public static Camera getCurrentCamera()
	{
		return(s_currentCamera);
	}
	
}
